package game.Utils;

import game.Sprites.SpriteResources;
import game.Vector3;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
import javafx.scene.transform.Rotate;

import javax.imageio.ImageReader;
import javax.imageio.ImageWriter;
import java.awt.image.BufferedImage;

public class GraphicsUtils {

    private static void rotate(GraphicsContext gc, double angle, double px, double py) {
        Rotate r = new Rotate(angle, px, py);
        gc.setTransform(r.getMxx(), r.getMyx(), r.getMxy(), r.getMyy(), r.getTx(), r.getTy());
    }

    /**
     * Draws an image on a graphics context.
     *
     * The image is drawn at (tlpx, tlpy) rotated by angle pivoted around the point:
     *   (tlpx + image.getWidth() / 2, tlpy + image.getHeight() / 2)
     *
     * @param gc the graphics context the image is to be drawn on.
     * @param angle the angle of rotation. in radians
     * @param x the top left x co-ordinate where the image will be plotted (in canvas co-ordinates).
     * @param y the top left y co-ordinate where the image will be plotted (in canvas co-ordinates).
     */
    public static void drawRotatedImage(GraphicsContext gc, Image image, double angle, double x, double y, double w, double h) {
        gc.save(); // saves the current state on stack, including the current transform
        rotate(gc, Math.toDegrees(angle), x + w / 2, y + h / 2);
        gc.drawImage(image, x, y, w, h);
        gc.restore(); // back to original state (before rotation)
    }

    public static void drawSpriteShadow(GraphicsContext gc, Vector3 screenPos, double sizeX,  double sizeY, double squareRes) {
        gc.drawImage(SpriteResources.getShadowImage(),
                screenPos.x - squareRes*sizeX / 2, screenPos.y - squareRes*sizeY / 2,
                squareRes*sizeX, squareRes*sizeY);
    }

    public static Image getSubimage(Image src, int x, int y, int w, int h)
    {
        PixelReader pr =  src.getPixelReader();
        PixelWriter pw = null;

        WritableImage wImg = new WritableImage( w, h );

        pw = wImg.getPixelWriter();

        for(int readY = 0 ; readY < h; readY++) {
            for(int readX = 0; readX < w; readX++) {
                //get pixel at X+x  & Y+y position
                Color color = pr.getColor( readX + x, readY + y);

                //set pixel to writableimage through pixel writer
                pw.setColor(readX, readY, color);
            }
        }

        return wImg;
    }

    public static void multiplyColor(PixelReader pixelReader, PixelWriter pixelWriter, int x, int y, Color c){
        Color srcC = pixelReader.getColor(x, y);
        Color dstC = new Color(srcC.getRed()*c.getRed(),srcC.getGreen()*c.getGreen(),
                srcC.getBlue()*c.getBlue(), 1.0);

        pixelWriter.setColor(x, y, dstC);
    }
    public static void multiplyRect(PixelReader pixelReader, PixelWriter pixelWriter, int x0, int y0, int w, int h, Color c){
        for(int x = x0; x < x0+w; x++){
            for(int y = y0; y < y0+h; y++){
                multiplyColor(pixelReader, pixelWriter, x, y, c);
            }
        }
    }

    public static void changeColor(PixelReader pixelReader, PixelWriter pixelWriter, Color sourceColor, Color dstColor){

    }

    public static Image changeColor(Image src, Color sourceColor, Color dstColor)
    {
        PixelReader pr =  src.getPixelReader();
        PixelWriter pw = null;

        int w = (int)src.getWidth(); int h = (int)src.getHeight();
        WritableImage wImg = new WritableImage( w, h );

        pw = wImg.getPixelWriter();

        for(int readY = 0 ; readY < h; readY++) {
            for(int readX = 0; readX < w; readX++) {
                Color color = pr.getColor( readX , readY );

                if(color.equals(sourceColor)){
                    pw.setColor(readX, readY, dstColor);
                }else{
                    pw.setColor(readX, readY, color);
                }
            }
        }

        return wImg;
    }
}
